package com.delayqueue.core.queue;

import com.delayqueue.common.task.CycleTask;
import com.delayqueue.common.task.Task;
import com.delayqueue.core.common.TimeUtil;
import com.delayqueue.core.executor.Executor;
import com.delayqueue.core.executor.ExecutorFactory;
import com.delayqueue.core.permanent.PermanentHandler;
import com.delayqueue.core.thread.ThreadHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.DelayQueue;

@Slf4j
@Component
public class QueueConsumer implements Runnable {

    @Autowired
    private ThreadHandler threadHandler;

    @Autowired
    private ExecutorFactory executorFactory;

    @Autowired
    private PermanentHandler permanentHandler;

    @Override
    public void run() {

        DelayQueue<Task> queue = QueueData.queue;
        try {
            while (true) {
                Task task = queue.take();
                if (task.isAsync()) {
                    threadHandler.execute(() -> {
                        executeTask(task);
                    });
                } else {
                    executeTask(task);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void executeTask(Task task) {
        if (!task.canExecute()) {
            log.info("不予执行：{}", task.getCode());
            return;
        }
        Executor executor = executorFactory.getExecutor(task);
        executor.execute(task);
        if (task.isCycle()) {
            long nextExecuteTime;
            do {
                nextExecuteTime = TimeUtil.getNextTime(task.getExecuteTime(), ((CycleTask) task).getCycleTimeNum(), ((CycleTask) task).getCycleTimeUnit());
            } while (nextExecuteTime < System.currentTimeMillis());
            task.setExecuteTime(nextExecuteTime);
            QueueData.addTask(task);
            log.info("已重新入队：{}/{}，下次执行时间：{}", task.getCode(), task.getExecutorType().getName(), TimeUtil.getLocalDateTime(task.getExecuteTime()));
        } else {
            permanentHandler.addCompleted(task);
            log.info("已执行：{}/{}，队列大小：{}", task.getCode(), task.getExecutorType().getName(), QueueData.queueSize());
        }
    }
}
